lib: defer source map payload decoding until first use - #65490
Conversation
With source maps enabled, every module that carries a sourceMappingURL had its map decoded (or read from disk), JSON-parsed and its sources resolved to absolute URLs while the module was being loaded, and the per-line length table used for coverage was built with a per-code-point loop. None of that is needed unless a stack trace is later mapped. Keep the URL on the cache entry and resolve the payload on the first findSourceMap() for that file. Under NODE_V8_COVERAGE the payload is still resolved at load time, since the cache is serialized during shutdown. lineLengths() now splits on '\n' with indexOf and only falls back to the code point walk when the source contains U+2028/U+2029. Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
|
Review requested:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #65490 +/- ##
==========================================
- Coverage 90.12% 90.12% -0.01%
==========================================
Files 752 751 -1
Lines 252315 252473 +158
Branches 47444 47493 +49
==========================================
+ Hits 227395 227529 +134
- Misses 16217 16258 +41
+ Partials 8703 8686 -17 🚀 New features to boost your workflow:
|
Failed to start CI- Validating Jenkins credentials ✔ Jenkins credentials valid - Starting PR CI job ✘ Failed to start PR CI: 400 Bad Requesthttps://github.com/nodejs/node/actions/runs/32767670990 |
Failed to start CI- Validating Jenkins credentials ✔ Jenkins credentials valid - Starting PR CI job ✘ Failed to start PR CI: 400 Bad Requesthttps://github.com/nodejs/node/actions/runs/32773413890 |
|
Benchmark GHA (module / module-require-source-map): https://github.com/nodejs/node/actions/runs/32775457259 Results
Benchmark results:
|
Commit Queue failed
The pull request was removed from the Commit Queue and labeled
commit-queue-failed
Full Commit Queue output |
With source maps enabled, stops decoding, reading and parsing every module's source map while the module loads; the payload is resolved the first time a stack trace (or
module.findSourceMap()) needs it.benchmark/module/module-require-source-map.js(new;require()of 1000 ~45-line modules with source maps enabled), 30 runs:data:URL) maps.mapfilesUnder
--enable-source-maps,process.setSourceMapsEnabled(true)orNODE_V8_COVERAGE, every module carrying asourceMappingURLhad its map decoded from the data: URL or read from disk, JSON-parsed and itssourcesresolved while loading, and the per-line length table used for coverage was built with a per-code-point loop over the source. None of that is needed unless a stack trace through that file is later mapped, so applications that ship source maps paid for all of them at startup.The cache entry now keeps the URL and resolves the payload on the first
findSourceMap()for that file, which is what stack trace preparation andmodule.findSourceMap()go through. UnderNODE_V8_COVERAGEthe payload is still resolved at load time, since the cache is serialized during shutdown when no more JS may run.lineLengths()splits on\nwithindexOfand only falls back to the code point walk when the source contains U+2028/U+2029; its output is unchanged.Tests: existing source-map, coverage,
getCallSitesandnode-output-sourcemapstests pass unchanged; they cover mapped stack traces,findSourceMap(), invalid maps and the coverage cache serialization.Disclosure: the code, benchmark, measurements and this description were written by Claude Code, directed and reviewed by @codebytere.